<template>
    <div class="advance-container">
        <el-button v-if="showImport" @click="showImportDialog" type="primary">高级导入</el-button>
        <el-button v-if="showExport" @click="showExportDialog" type="primary">高级导出</el-button>
        <edu-dialog
            :title="title"
            ref="advDialog"
            :show-buttons="false"
            @close="close"
            @opened="opened"
            width="800px"
        >
            <el-row :gutter="10" id="opr-zone">
                <el-col :span="11">
                    <el-form label-suffix="：" label-position="left" label-width="120px">
                        <el-form-item :label="label">
                            <el-select
                                style="width:100%"
                                v-model="selectedSchemeId"
                                @change="handleChangeScheme"
                                clearable
                            >
                                <el-option
                                    v-for="(item,index_) in schemes"
                                    :key="index_"
                                    :label="item.label"
                                    :value="item.value"
                                ></el-option>
                            </el-select>
                        </el-form-item>
                    </el-form>
                </el-col>
                <el-col :span="13">
                    <el-button type="primary" @click="saveScheme">保存方案</el-button>
                    <el-button type="primary" @click="removeScheme">删除方案</el-button>
                    <el-button
                        v-if="isImport"
                        @click="openImportDialog"
                        type="primary"
                    >{{$t("message.import")}}</el-button>
                    <el-button v-if="isExport" @click="exportScheme">{{$t("message.export")}}</el-button>
                    <el-button type="primary" @click="clearNames">清空命名</el-button>
                </el-col>
            </el-row>
            <edu-table
                v-if="isImport"
                size="mini"
                :data="fields"
                :pagination="false"
                :selection="false"
                ref="tabList"
                :order="false"
                @keyup.native="handleKeyUp"
            >
                <el-table-column width="60" align="center">
                    <template slot="header" slot-scope="scope">
                        <el-checkbox
                            v-model="selected"
                            key="checkAll"
                            @change="handleCheckAll"
                            :indeterminate="isIndeterminate"
                        />
                    </template>
                    <template slot-scope="scope">
                        <el-checkbox
                            v-model="scope.row.selected"
                            :key="'check-'+scope.row.rowIndex"
                            @change="handleCheckSingle(scope)"
                            :indeterminate="scope.row.isIndeterminate"
                        />
                    </template>
                </el-table-column>
                <el-table-column label="序号" width="60" align="center">
                    <template slot-scope="scope">
                        <div>{{ scope.row.seq }}</div>
                    </template>
                </el-table-column>
                <el-table-column label="业务字段名">
                    <template slot-scope="scope">
                        <div :class="scope.row.isClass?'field-clazz field-name':'field-name'">
                            <span @click="handleFieldClazzFold(scope)">{{ scope.row.name }}</span>
                            <span
                                @click="handleFieldClazzFold(scope)"
                                v-if="scope.row.isClass"
                                :class="scope.row.isFold?'arrow-up':'arrow-down'"
                            ></span>
                        </div>
                    </template>
                </el-table-column>
                <el-table-column label="导入字段名">
                    <template slot-scope="scope">
                        <el-input
                            v-if="!scope.row.isClass"
                            type="text"
                            v-model="scope.row.text"
                            maxlength="50"
                            :style="scope.row.isRepeat?{'border':'1px solid red'}:null"
                            v-show="scope.row.selected"
                            :attr-name="scope.row.id"
                            attr-type="field"
                        />
                    </template>
                </el-table-column>
            </edu-table>
            <edu-table
                v-if="isExport"
                size="mini"
                :data="fields"
                :pagination="false"
                :selection="false"
                ref="tabList"
                :order="false"
                @keyup.native="handleKeyUp"
            >
                <el-table-column width="60" align="center">
                    <template slot="header" slot-scope="scope">
                        <el-checkbox
                            v-model="selected"
                            key="checkAll"
                            @change="handleCheckAll"
                            :indeterminate="isIndeterminate"
                        />
                    </template>
                    <template slot-scope="scope">
                        <el-checkbox
                            v-model="scope.row.selected"
                            :key="'check-'+scope.row.rowIndex"
                            @change="handleCheckSingle(scope)"
                            :indeterminate="scope.row.isIndeterminate"
                        />
                    </template>
                </el-table-column>
                <el-table-column label="序号" width="60" align="center">
                    <template slot-scope="scope">
                        <div>{{ scope.row.seq }}</div>
                    </template>
                </el-table-column>
                <el-table-column label="业务字段名">
                    <template slot-scope="scope">
                        <div :class="scope.row.isClass?'field-clazz field-name':'field-name'">
                            <span @click="handleFieldClazzFold(scope)">{{ scope.row.name }}</span>
                            <span
                                @click="handleFieldClazzFold(scope)"
                                v-if="scope.row.isClass"
                                :class="scope.row.isFold?'arrow-up':'arrow-down'"
                            ></span>
                        </div>
                    </template>
                </el-table-column>
                <el-table-column label="导出字段名">
                    <template slot-scope="scope">
                        <el-input
                            v-if="!scope.row.isClass"
                            type="text"
                            v-model="scope.row.text"
                            maxlength="50"
                            :style="scope.row.isRepeat?{'border':'1px solid red'}:null"
                            v-show="scope.row.selected"
                            :attr-name="scope.row.id"
                            attr-type="field"
                        />
                    </template>
                </el-table-column>
                <el-table-column label="导出列顺序" width="100">
                    <template slot-scope="scope">
                        <el-input
                            type="text"
                            v-model="scope.row.order"
                            :style="scope.row.isError||scope.row.isOrderRepeat?{'border':'1px solid red'}:null"
                            v-show="scope.row.selected"
                            v-if="!scope.row.isClass"
                            :attr-name="scope.row.id"
                            attr-type="order"
                        />
                    </template>
                </el-table-column>
            </edu-table>
        </edu-dialog>
        <!--导入对话框-->
        <edu-dialog :title="title" ref="importDialog">
            <template slot="buttons">
                <el-button @click="cancelImport">{{$t('message.cancel')}}</el-button>
                <el-button type="primary" @click="uploadImport">{{$t('message.submit')}}</el-button>
            </template>
            <div>
                <el-form label-width="85px">
                    <el-form-item>
                        <el-upload
                            :auto-upload="false"
                            ref="upload"
                            :data="{schemeId:this.selectedSchemeId}"
                            :on-success="handleSuccess"
                            :on-error="handleError"
                            :before-upload="handleBefore"
                            :limit="1"
                            accept=".xlsx"
                            :action="importApi"
                        >
                            <el-button
                                slot="trigger"
                                size="small"
                                type="primary"
                            >{{$t('label.selectFile')}}</el-button>
                            <div slot="tip" class="el-upload__tip">只能上传.xlsx文件</div>
                        </el-upload>
                    </el-form-item>
                </el-form>
            </div>
        </edu-dialog>
    </div>
</template>
<script>
import fetch from "common/src/utils/fetch";
import { fieldType } from "common/src/api/studentinfo";
export default {
    name: "AdvanceImportExport",
    props: {
        showImport: {
            default: false,
            type: Boolean
        },
        showExport: {
            default: false,
            type: Boolean
        },
        businessType: {
            type: String,
            required: true
        },
        //字段列表接口，各业务类型自己提供
        fieldsApi: {
            type: String,
            required: true
        },
        //字段列表接口请求方式
        fieldsApiMethod: {
            type: String,
            default: "get"
        },
        //字段列表接口请求参数
        fieldsApiParams: {
            type: Object,
            default: null
        },
        //筛选条件导出接口
        conditionExportApi: {
            default: null,
            type: String
        },
        //id列表导出接口
        idsExportApi: {
            default: null,
            type: String
        },
        importApi: {
            default: null,
            type: String
        },
        asynExport: {
            default: false,
            type: Boolean
        },
        getExportParamMethod: {
            type: Function,
            default: null
        },
        exportTotal: {
            default: 0
        }
    },
    data() {
        return {
            type: 0, //导入1，导出2
            preUrl: "/api/studentservice/advancedImpExp/",
            title: null,
            isExport: false,
            isImport: false,
            label: null,
            fields: null,
            selectedSchemeId: null,
            schemes: null,
            rawData: null,
            fieldClass: null,
            selected: false, //全选
            isIndeterminate: false,
            selectType: {
                NONE: false,
                SELECTED: true
            },
            clazzIds: [],
            fieldIds: [],
            clazzIndeterminateIds: [],
            baseClassId: 1, //基础信息id
            aliasMap: new Map(), //字段id与别名映射，在修改字段时更新
            keyMap: new Map(), //字段Id与主键id映射
            orderMap: new Map(), //字段id与排序映射
            STUDENT_ID: "STUDENT_ID_"
        };
    },
    methods: {
        resetAndOpenDialog() {
            this.selectedSchemeId = null;
            this.reset();
            this.$refs.advDialog.open();
        },
        opened() {
            let loading = this.$loading({
                lock: true,
                text: "Loading",
                spinner: "el-icon-loading",
                background: "rgba(255, 255, 255, .48)"
            });
            Promise.all([this.getSchemes(false), this.getFieldType()]).finally(
                () => {
                    loading.close();
                }
            );
        },
        showImportDialog() {
            this.title = this.$t("message.import");
            this.label = "导入方案名称";
            this.isImport = true;
            this.isExport = false;
            this.type = 1;
            this.resetAndOpenDialog();
        },
        showExportDialog() {
            this.title = this.$t("message.export");
            this.label = "导出方案名称";
            this.isImport = false;
            this.isExport = true;
            this.type = 2;
            this.resetAndOpenDialog();
        },
        reset() {
            this.aliasMap.clear();
            this.keyMap.clear();
            this.orderMap.clear();
            this.fieldIds.length = 0;
            this.clazzIds.length = 0;
            this.clazzIndeterminateIds.length = 0;
            this.fields = null;
            this.selected = false;
            this.isIndeterminate = false;
        },
        //获取业务字段列表
        getFields() {
            let that = this;
            return new Promise((resolve, reject) => {
                if (that.rawData != null) {
                    this.initFields();
                    return resolve();
                }
                if (that.fieldsApi) {
                    let params = {
                        url: that.fieldsApi,
                        method: that.fieldsApiMethod,
                        showMask: false
                    };
                    if (that.fieldsApiMethod != "get") {
                        params.data = that.fieldsApiParams;
                    }
                    return fetch(params)
                        .then(res => {
                            if (res.code == 200) {
                                res.data.forEach(row => {
                                    row.text = null;
                                    row.order = null;
                                    row.isError = null;
                                    row.isRepeat = false;
                                    row.isOrderRepeat = false;
                                    row.selected = this.selectType.NONE; //默认未选中
                                });
                                that.rawData = res.data;
                                this.initFields();
                                resolve();
                            } else {
                                reject(res.code);
                            }
                        })
                        .catch(err => {
                            reject(err);
                        });
                } else {
                    this.$message({
                        type: "warning",
                        message: "fieldsApi未配置"
                    });
                    reject();
                }
            });
        },
        //获取业务方案
        getSchemes(showMask = true) {
            let that = this;
            return new Promise((resolve, reject) => {
                fetch({
                    url:
                        that.preUrl +
                        "getAdvanImpExpScheme?businessType=" +
                        that.businessType +
                        "&type=" +
                        that.type,
                    showMask: showMask
                })
                    .then(res => {
                        if (res.code == 200) {
                            that.schemes = res.data.map(scheme => {
                                return {
                                    label: scheme.name,
                                    value: scheme.id
                                };
                            });
                            resolve();
                        } else {
                            reject(res.code);
                        }
                    })
                    .catch(err => {
                        reject(err);
                    });
            });
        },
        getFieldType() {
            return new Promise((resolve, reject) => {
                if (this.fieldClass != null) {
                    this.getFields().finally(() => {
                        resolve();
                    });
                } else {
                    fieldType()
                        .then(res => {
                            if (res.code == 200) {
                                this.fieldClass = res.data;
                                this.getFields().finally(() => {
                                    resolve();
                                });
                            } else {
                                reject(res.code);
                            }
                        })
                        .catch(err => {
                            reject(err);
                        });
                }
            });
        },
        initFields(fieldClazz = null, show = true) {
            let fields = [];
            if (this.fieldClass && this.fieldClass.length > 0) {
                let currentFieldClazz = null;
                if (fieldClazz == null) {
                    currentFieldClazz = this.fieldClass[0].nameEn;
                } else {
                    currentFieldClazz = fieldClazz;
                }
                let rowIndex = -1;
                this.fieldClass.forEach(clazz => {
                    rowIndex++;
                    let field = {
                        id: clazz.id,
                        isClass: true,
                        name: clazz.name,
                        nameEn: clazz.nameEn,
                        isFold: true,
                        rowIndex: rowIndex,
                        selected: this.clazzIds.includes(clazz.id)
                            ? this.selectType.SELECTED
                            : this.selectType.NONE,
                        isIndeterminate: this.clazzIds.includes(clazz.id)
                            ? false
                            : this.clazzIndeterminateIds.includes(clazz.id)
                    };
                    fields.push(field);
                    if (clazz.nameEn == currentFieldClazz && show) {
                        field.isFold = false;
                        this.rawData
                            .filter(field =>
                                clazz.nameEn.split(",").includes(field.tableStr)
                            )
                            .forEach((f, index_) => {
                                let field = _.cloneDeep(f);
                                rowIndex++;
                                field.text = this.aliasMap.has(f.id)
                                    ? this.aliasMap.get(f.id)
                                    : null;
                                field.rowIndex = rowIndex;
                                field.selected = this.selectType.NONE;
                                field.seq = index_ + 1;
                                field.order = this.orderMap.has(f.id)
                                    ? this.orderMap.get(f.id)
                                    : null;
                                fields.push(field);
                            });
                    }
                });
            }
            this.fields = fields;
            this.defaultSelectStudentId();
        },
        saveScheme() {
            if (!this.validateSelectItem()) {
                return;
            }
            if (this.selectedSchemeId) {
                this.updateScheme();
            } else {
                this.addScheme();
            }
        },
        addScheme() {
            this.$prompt(
                "请输入" + this.title + "方案名称",
                this.$t("message.prompt"),
                {
                    confirmButtonText: this.$t("message.confirm"),
                    cancelButtonText: this.$t("message.cancel"),
                    inputValidator: value => {
                        if (value == null || value == "") {
                            return false;
                        }
                        if (value.indexOf(" ") != -1) {
                            return false;
                        }
                        if (value.length > 15) {
                            return false;
                        }
                        return true;
                    },
                    inputErrorMessage:
                        "必须填写，且不能包含空格，长度不超过15个字符"
                }
            )
                .then(result => {
                    let fn = () => {
                        let params = {
                            type: this.type,
                            businessType: this.businessType,
                            name: result.value,
                            fields: this.rawData
                                .filter(f => this.fieldIds.includes(f.id))
                                .map(f => {
                                    let text = this.aliasMap.get(f.id);
                                    let order = this.orderMap.get(f.id);
                                    return {
                                        businessFieldId: f.id,
                                        businessTable: f.tableStr,
                                        excelField: text,
                                        fieldIndex: order
                                    };
                                })
                        };
                        fetch({
                            url: this.preUrl + "addAdvancedImpExp",
                            method: "post",
                            data: params
                        }).then(res => {
                            if (res.code == 200) {
                                this.$message({
                                    type: "success",
                                    message: "添加成功"
                                });
                                this.reset();
                                this.initFields();
                                this.getSchemes();
                            }
                        });
                    };
                    this.validateSchemeDuplicate(result.value, fn);
                })
                .catch(err => {
                    console.log(err);
                });
        },
        updateScheme() {
            let params = {
                id: this.selectedSchemeId,
                type: this.type,
                businessType: this.businessType,
                name: this.schemes.find(s => s.value == this.selectedSchemeId)
                    .label
            };
            params.fields = this.fieldIds.map(id => {
                let field = this.rawData.find(f => f.id == id);
                return {
                    id: this.keyMap.has(id) ? this.keyMap.get(id) : null,
                    businessFieldId: id,
                    businessTable: field.tableStr,
                    excelField: this.aliasMap.has(id)
                        ? this.aliasMap.get(id)
                        : null,
                    schemeId: this.selectedSchemeId,
                    fieldIndex: this.orderMap.has(id)
                        ? this.orderMap.get(id)
                        : null
                };
            });
            fetch({
                url: this.preUrl + "addAdvancedImpExp",
                method: "post",
                data: params
            }).then(res => {
                if (res.code == 200) {
                    this.$message({
                        type: "success",
                        message: "更新成功"
                    });
                    this.getSchemeDetail();
                }
            });
        },
        //删除方案
        removeScheme() {
            if (!this.selectedSchemeId) {
                this.$message({
                    type: "warning",
                    message: "请选择要删除的方案"
                });
                return;
            }
            this.$confirm(
                "是否确认删除该高级" + this.title + "方案？",
                this.$t("message.prompt"),
                {
                    confirmButtonText: this.$t("message.yes"),
                    cancelButtonText: this.$t("message.no"),
                    type: "warning"
                }
            ).then(() => {
                fetch({
                    url:
                        this.preUrl +
                        "deleteAdvanImpExpScheme?schemeId=" +
                        this.selectedSchemeId,
                    method: "get"
                }).then(res => {
                    if (res.code == 200) {
                        this.$message({
                            type: "success",
                            message: this.$t("message.deleteSuccess")
                        });
                        this.schemes = this.schemes.filter(
                            scheme => scheme.value != this.selectedSchemeId
                        );
                        this.selectedSchemeId = null;
                        this.reset();
                        this.initFields();
                    }
                });
            });
        },
        getSchemeDetail() {
            fetch({
                url:
                    this.preUrl +
                    "getAdvanImpExpField?schemeId=" +
                    this.selectedSchemeId
            }).then(res => {
                if (res.code == 200 && res.data) {
                    this.reset();
                    //第一步：设置映射关系
                    res.data.forEach(f => {
                        if (f.excelField != null && f.excelField != "") {
                            this.aliasMap.set(f.businessFieldId, f.excelField);
                        }
                        if (f.fieldIndex != null && f.fieldIndex != "") {
                            this.orderMap.set(f.businessFieldId, f.fieldIndex);
                        }
                        this.keyMap.set(f.businessFieldId, f.id);
                    });
                    //第二步：初始化字段列表
                    this.initFields();
                    //第三步：初始化复选框状态
                    res.data.forEach(f => {
                        let field = this.fields.find(
                            field =>
                                !field.isClass && field.id == f.businessFieldId
                        );
                        //展开列表若包含字段，则模拟点击;不包含，只记录字段id
                        if (field) {
                            field.selected = this.selectType.SELECTED;
                            this.handleCheckSingle({ row: field });
                        } else {
                            this.fieldIds.push(f.businessFieldId);
                        }
                    });
                    //第四步：更新字段分类状态
                    this.fields
                        .filter(f => f.isClass)
                        .forEach(clazz => {
                            let names = clazz.nameEn.split(",");
                            let ids = this.rawData
                                .filter(f => names.includes(f.tableStr))
                                .map(f => f.id);
                            let diffs = _.without(
                                ids,
                                ...res.data.map(f => f.businessFieldId)
                            );
                            if (diffs.length == 0) {
                                if (!this.clazzIds.includes(clazz.id)) {
                                    this.clazzIds.push(clazz.id);
                                }
                                clazz.selected = this.selectType.SELECTED;
                            } else if (diffs.length < ids.length) {
                                clazz.isIndeterminate = true;
                                if (
                                    !this.clazzIndeterminateIds.includes(
                                        clazz.id
                                    )
                                ) {
                                    this.clazzIndeterminateIds.push(clazz.id);
                                }
                            }
                        });
                    //第五步：更新总复选框状态
                    this.updateGlobaCheckBoxStatus();
                }
            });
        },
        //验证选中项
        validateSelectItem() {
            if (this.fieldIds.length == 0) {
                this.$message({
                    type: "warning",
                    message: "方案必须选择业务字段"
                });
                return false;
            }
            //TODO:isError，isRepeat，isOrderRepeat清空
            if (!this.validateFieldRepeat()) {
                this.$message({
                    type: "warning",
                    message: this.isImport
                        ? "导入字段名称不可重复"
                        : "导出列名称不能重复"
                });
                return false;
            }
            if (this.isExport && !this.validateFieldOrder()) {
                this.$message({
                    type: "warning",
                    message: "导出顺序必须是整数"
                });
                return false;
            }
            if (this.isExport && !this.validateOrderRepeat()) {
                this.$message({
                    type: "warning",
                    message: "导出列顺序不能重复"
                });
                return false;
            }
            return true;
        },
        //验证方案是否重复
        validateSchemeDuplicate(name, fn) {
            if (this.schemes.some(s => s.label == name)) {
                this.$confirm(
                    "当前方案名称重复，是否需要覆盖?",
                    this.$t("message.prompt"),
                    {
                        confirmButtonText: this.$t("message.confirm"),
                        cancelButtonText: this.$t("message.cancel"),
                        type: "warning"
                    }
                ).then(() => {
                    fn();
                });
            } else {
                fn();
            }
        },
        //校验字段名是否重复
        validateFieldRepeat() {
            //TODO:提示具体某一行
            let flag = true;
            let items = this.fieldIds;
            for (let i = 0; i < items.length - 1; i++) {
                for (let j = i + 1; j < items.length; j++) {
                    if (
                        this.aliasMap.has(items[i]) &&
                        this.aliasMap.has(items[j])
                    ) {
                        let a = this.aliasMap.get(items[i]);
                        let b = this.aliasMap.get(items[j]);
                        if (a != "" && a == b) {
                            flag = false;
                        }
                    }
                }
                if (!flag) {
                    break;
                }
            }
            return flag;
        },
        //校验顺序是否重复
        validateOrderRepeat() {
            //TODO:提示具体某一行
            let flag = true;
            let items = [...this.orderMap.keys()]
                .map(id => {
                    return {
                        id: id,
                        order: this.orderMap.get(id)
                    };
                })
                .filter(o => o.order != null && o.order != "");
            for (let i = 0; i < items.length - 1; i++) {
                for (let j = i + 1; j < items.length; j++) {
                    if (items[i].order == items[j].order) {
                        flag = false;
                    }
                }
                if (!flag) {
                    break;
                }
            }
            return flag;
        },
        //校验顺序是否合法
        validateFieldOrder() {
            //TODO:提示具体某一行
            let flag = true;
            for (let key of this.orderMap.keys()) {
                let val = this.orderMap.get(key);
                if (val != null && val != "" && !/^[0-9]+$/.test(val)) {
                    flag = false;
                }
            }
            return flag;
        },
        exportScheme() {
            if (!this.selectedSchemeId) {
                this.$message({
                    type: "warning",
                    message: "请选择要导出的方案"
                });
                return;
            }
            if (this.conditionExportApi) {
                let startExport = () => {
                    let data = null,
                        method = null,
                        url = null;
                    if (this.getExportParamMethod) {
                        let result = this.getExportParamMethod();
                        url = result.condition
                            ? this.conditionExportApi
                            : this.idsExportApi;

                        method = result.method || "get";
                        if (method === "get") {
                            url += "?" + result.params;
                        } else if (method === "post") {
                            data = result.params;
                        }
                    }
                    if (!this.asynExport) {
                        window.open(url);
                    } else {
                        let loading = this.$loading({
                            lock: true,
                            text: "Loading",
                            spinner: "el-icon-loading",
                            background: "rgba(255, 255, 255, .48)"
                        });
                        fetch({
                            url: url,
                            data: data,
                            method: method,
                            showMask: false
                        }).then(res => {
                            if (res.code == 200) {
                                this.delayRequest(res.data.key, loading);
                            } else {
                                loading.close();
                            }
                        });
                    }
                };
                if (this.exportTotal >= 20000) {
                    this.$confirm(
                        "当前导出的学生数据量超过20000，导出将持续很长时间，建议进行筛选后再进行导出。请确认是否继续？",
                        this.$t("message.prompt"),
                        {
                            confirmButtonText: this.$t("message.confirm"),
                            cancelButtonText: this.$t("message.cancel"),
                            type: "warning"
                        }
                    )
                        .then(() => {
                            startExport();
                        })
                        .catch(() => {
                            this.$refs.advDialog.close();
                        });
                } else {
                    startExport();
                }
            }
        },
        async delayRequest(key, loading) {
            await new Promise(resolve => setTimeout(resolve, 5000));
            fetch({
                url: "/api/studentservice/stuAppoint/result/" + key,
                showMask: false
            })
                .then(res => {
                    if (res.code == 200 && res.data.status) {
                        loading.close();
                        let path =
                            "/api/studentservice/studentInfo/exportStudentManageList?path=" +
                            res.data.path;
                        window.open(path);
                    } else {
                        this.delayRequest(key, loading);
                    }
                })
                .catch(err => {
                    loading.close();
                    throw err;
                });
        },
        openImportDialog() {
            if (!this.selectedSchemeId) {
                this.$message({
                    type: "warning",
                    message: "请选择要导入的方案"
                });
                return;
            }
            this.$refs.importDialog.open();
            this.clearFiles();
        },
        //上传导入
        uploadImport() {
            this.$refs.upload.submit();
        },
        //取消导入
        cancelImport() {
            this.$refs.importDialog.close();
        },
        handleChangeScheme() {
            if (this.selectedSchemeId) {
                this.getSchemeDetail();
            } else {
                this.reset();
                this.initFields();
            }
            this.$emit("change-scheme", this.selectedSchemeId);
        },
        handleBefore(file) {
            const isLt2M = file.size / 1024 / 1024 < 10;
            if (!isLt2M) {
                this.$message.error("上传文件大小不能超过 10MB!");
                this.clearFiles();
                return false;
            }
            const types = [
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            ];
            if (!types.includes(file.type)) {
                this.$message.error("上传文件格式必须是.xlsx");
                this.clearFiles();
                return false;
            }
        },
        handleSuccess(res, file, fileList) {
            if (res.code == 200) {
                this.$message({
                    type: "success",
                    message: this.$t("common.tips.uploadSuccess")
                });
                this.$refs.importDialog.close();
            } else {
                let msg = "";
                res.data.forEach(m => {
                    msg += "<div style='margin:5px 0'>" + m + "</div>";
                });
                this.$message({
                    duration: 5000,
                    type: "error",
                    dangerouslyUseHTMLString: true,
                    message: msg
                });
                this.clearFiles();
            }
        },
        handleError(err, file, fileList) {
            let msg = JSON.parse(err.message);
            this.$message({
                type: "error",
                message: msg.message
            });
        },
        handleCheckAll() {
            this.fields.forEach(field => {
                field.selected = this.selected;
                if (field.isClass) {
                    field.isIndeterminate = false;
                }
            });
            this.isIndeterminate = false;
            this.updateSelectedIds(null, true);
            //导入时，若取消全选，则选中学号
            if (this.isImport && this.selected == this.selectType.NONE) {
                let column = this.fields.find(
                    f => !f.isClass && f.columnStr === this.STUDENT_ID
                );
                if (column) {
                    column.selected = this.selectType.SELECTED;
                }
                column = this.rawData.find(
                    f => f.columnStr === this.STUDENT_ID
                );
                if (column) {
                    this.fieldIds.push(column.id);
                }
                //处理分类状态
                let clazz = this.fields.find(
                    f => f.isClass && f.id == this.baseClassId
                );
                if (clazz) {
                    clazz.isIndeterminate = true;
                    this.clazzIndeterminateIds.push(clazz.id);
                }
                this.isIndeterminate = true;
            }
        },
        handleCheckSingle(scope) {
            if (!scope.row.isClass) {
                this.selectedStudentId(scope.row);
            }
            this.updateRelationSelected(scope.row);
            this.updateSelectedIds(scope.row);
            //导入时，若取消基础信息，默认选中学号
            if (
                this.isImport &&
                scope.row.isClass &&
                scope.row.selected == this.selectType.NONE &&
                scope.row.id == this.baseClassId
            ) {
                if (scope.row.isFold) {
                    scope.row.isIndeterminate = true;
                    this.clazzIndeterminateIds.push(scope.row.id);
                    let column = this.rawData.find(
                        f => f.columnStr === this.STUDENT_ID
                    );
                    if (column) {
                        this.fieldIds.push(column.id);
                    }
                    this.isIndeterminate = true;
                } else {
                    this.defaultSelectStudentId();
                }
            }
        },
        handleFieldClazzFold(scope) {
            scope.row.isFold = !scope.row.isFold;
            this.initFields(scope.row.nameEn, !scope.row.isFold);
            this.setSelectedStatus();
            this.$nextTick(() => {
                this.scrollToTop();
            });
        },
        handleKeyUp(event) {
            if (event.srcElement.className == "el-input__inner") {
                let type = event.srcElement.getAttribute("attr-type");
                if (type === "field") {
                    this.aliasMap.set(
                        Number(event.srcElement.getAttribute("attr-name")),
                        event.srcElement.value
                    );
                }
                if (type === "order") {
                    this.orderMap.set(
                        Number(event.srcElement.getAttribute("attr-name")),
                        event.srcElement.value
                    );
                }
            }
        },
        //根据ids集合，设置字段或分类的选中信息
        setSelectedStatus() {
            this.fields.forEach(field => {
                if (field.isClass) {
                    if (this.clazzIds.includes(field.id)) {
                        field.selected = this.selectType.SELECTED;
                    }
                    if (this.clazzIndeterminateIds.includes(field.id)) {
                        field.isIndeterminate = true;
                    }
                } else {
                    if (this.fieldIds.includes(field.id)) {
                        field.selected = this.selectType.SELECTED;
                    }
                }
            });
        },
        //更新选中的Ids
        updateSelectedIds(item, isAll = false) {
            if (isAll) {
                this.clazzIndeterminateIds = [];
                this.clazzIds = this.selected
                    ? this.fieldClass.map(f => f.id)
                    : [];
                this.fieldIds = this.selected
                    ? this.rawData.map(f => f.id)
                    : [];
                return;
            }
            if (item) {
                if (item.isClass) {
                    let names = item.nameEn.split(",");
                    let ids = this.rawData
                        .filter(f => names.includes(f.tableStr))
                        .map(f => f.id);
                    if (item.selected == this.selectType.SELECTED) {
                        this.fieldIds = _.union(this.fieldIds, ids);
                    } else {
                        this.fieldIds = _.without(this.fieldIds, ...ids);
                    }
                } else {
                    if (item.selected == this.selectType.SELECTED) {
                        if (!this.fieldIds.includes(item.id))
                            this.fieldIds.push(item.id);
                    } else {
                        this.fieldIds = this.fieldIds.filter(
                            id => id != item.id
                        );
                    }
                }
            }
            this.clazzIds = this.fields
                .filter(
                    f => f.isClass && f.selected == this.selectType.SELECTED
                )
                .map(f => f.id);
            this.clazzIndeterminateIds = this.fields
                .filter(f => f.isClass && f.isIndeterminate)
                .map(f => f.id);
        },
        //更新关联项的选中
        updateRelationSelected(item) {
            if (item.isClass) {
                item.isIndeterminate = false;
                let names = item.nameEn.split(",");
                this.fields.forEach(field => {
                    if (!field.isClass && names.includes(field.tableStr)) {
                        field.selected = item.selected;
                    }
                });
            } else {
                this.fieldClass.forEach(clazz => {
                    let names = clazz.nameEn.split(",");
                    if (names.includes(item.tableStr)) {
                        let clazzField = this.fields.find(
                            field => field.isClass && clazz.id == field.id
                        );
                        let relation = this.fields.filter(field =>
                            names.includes(field.tableStr)
                        );
                        if (
                            relation.every(
                                field =>
                                    field.selected == this.selectType.SELECTED
                            )
                        ) {
                            clazzField.isIndeterminate = false;
                            clazzField.selected = this.selectType.SELECTED;
                        } else if (
                            relation.every(
                                field => field.selected == this.selectType.NONE
                            )
                        ) {
                            clazzField.isIndeterminate = false;
                            clazzField.selected = this.selectType.NONE;
                        } else {
                            clazzField.isIndeterminate = true;
                            clazzField.selected = this.selectType.NONE;
                        }
                    }
                });
            }
            this.updateGlobaCheckBoxStatus();
        },
        updateGlobaCheckBoxStatus() {
            let classes = this.fields.filter(field => field.isClass);
            if (classes.some(c => c.isIndeterminate)) {
                this.selected = this.selectType.NONE;
                this.isIndeterminate = true;
            } else {
                if (
                    classes.every(c => c.selected == this.selectType.SELECTED)
                ) {
                    this.isIndeterminate = false;
                    this.selected = this.selectType.SELECTED;
                } else if (
                    classes.every(c => c.selected == this.selectType.NONE)
                ) {
                    this.isIndeterminate = false;
                    this.selected = this.selectType.NONE;
                } else {
                    this.isIndeterminate = true;
                    this.selected = this.selectType.NONE;
                }
            }
        },
        //导入时，默认选中学号
        defaultSelectStudentId() {
            if (this.isImport) {
                let column = this.fields.find(
                    f => !f.isClass && f.columnStr === this.STUDENT_ID
                );
                if (column) {
                    column.selected = this.selectType.SELECTED;
                    this.handleCheckSingle({ row: column });
                }
            }
        },
        selectedStudentId(item) {
            if (this.isImport && item.columnStr === this.STUDENT_ID) {
                item.selected = this.selectType.SELECTED;
            }
        },
        clearFiles() {
            if (this.$refs.upload) this.$refs.upload.clearFiles();
        },
        clearNames() {
            this.fields.forEach(field => {
                if (!field.isClass) {
                    field.text = null;
                }
            });
            this.aliasMap.clear();
        },
        close() {},
        scrollToTop() {
            let content = document.getElementById("opr-zone").parentNode;
            content.scrollTop = 0;
        }
    }
};
</script>
<style lang="scss" scoped>
.advance-container {
    height: 32px;
    display: inline-block;
    margin-left: 10px;
}
.field-name {
    line-height: 32px;
    height: 32px;
}
.field-clazz {
    color: #3a7fe8;
    span {
        cursor: pointer;
    }
}
.arrow-down {
    position: relative;
    top: 3px;
    border: 5px solid #3a7fe8;
    border-left-color: transparent;
    border-right-color: transparent;
    border-bottom-color: transparent;
    display: inline-block;
    margin-left: 5px;
}
.arrow-up {
    position: relative;
    top: -3px;
    border: 5px solid #3a7fe8;
    border-left-color: transparent;
    border-right-color: transparent;
    border-top-color: transparent;
    display: inline-block;
    margin-left: 5px;
}
</style>
